package com.xjj.sso.server.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xjj.framework.utils.StringUtils;
import com.xjj.sso.project.cache.ProjectCache;
import com.xjj.sso.project.entity.ProjectEntity;
import com.xjj.sso.server.SSOConstants;
import com.xjj.sso.server.cache.TicketCache;
import com.xjj.sso.server.pojo.SSOIdentity;
import com.xjj.sso.server.pojo.User;
import com.xjj.sso.server.ticket.GrantingTicket;
import com.xjj.sso.server.ticket.ServiceTicket;
import com.xjj.sso.server.util.SSOConfiguration;
import com.xjj.sso.server.util.SSOUtils;


public class SSOHandlerSupport{
	public static String SSO_LOGIN_TYPE = SSOConfiguration.get("sso.login.type");
	public static int SSO_COOKIE_MAXAGE = SSOConfiguration.getInt("sso.cookie.maxage", -1);
	public static String SSO_COOKIE_NAME = SSOConfiguration.get("sso.cookie.name");
	public static String SSO_COOKIE_PATH = SSOConfiguration.get("sso.cookie.path");
	
	public static String SSO_URL_LOGIN = SSOConfiguration.get("sso.url.login");
	
	public static String SSO_URL_INDEX = SSOConfiguration.get("sso.url.index");
	public static String SSO_SERVER_ERROR = SSOConfiguration.get("sso.server.error");
	
	
	/**
	 * 获得sso的cookie值
	 * @param response
	 * @param ticket
	 */
	public String getSSOCookie(HttpServletRequest request,HttpServletResponse response)
	{
		Cookie[] cookies = request.getCookies();
		String gtCookie = null;
		if(null != cookies)
		{
			Cookie cookie = null;
			for (int i = 0; i < cookies.length; i++) {
				cookie = cookies[i];
				if(SSO_COOKIE_NAME.equals(cookie.getName()))
				{
					gtCookie = cookie.getValue();
					break;
				}
			}
		}
		return gtCookie;
	}
	
	/**
	 * 写cookie值
	 * @param response
	 * @param ticket
	 */
	public void writeCookie(HttpServletResponse response,String ticket)
	{
		Cookie cookie = new Cookie(SSO_COOKIE_NAME, ticket);		
		cookie.setMaxAge(SSO_COOKIE_MAXAGE);	
		cookie.setPath(SSO_COOKIE_PATH);
		
		response.addCookie(cookie);
	}
	
	public void removeSSOCookie(HttpServletRequest request,HttpServletResponse response, String name) {
		Cookie[] cookies = request.getCookies();
		if (null == cookies) {
			return;
		}

		for (Cookie cookie : cookies) {
			if (cookie.getName().equals(name)) {
				cookie.setValue(null);
				cookie.setMaxAge(0);// 立即销毁cookie
				cookie.setPath("/");
				response.addCookie(cookie);
				break;
			}
		}
	} 
	
	/**
	 * 强制踢出其他地方登陆的用户
	 * @param user
	 */
	public void ssoKickUser(HttpServletRequest request,HttpServletResponse response,User user) {
		
		// 清除cookie值
		removeSSOCookie(request,response, SSO_COOKIE_NAME);
		
		//查询是否该账户是否已经在其他地方登陆
		Object oldGTId = TicketCache.getSignedGtId(user.getUserId());
		
		GrantingTicket oldGT = null;
		if(null!=oldGTId)
		{
			oldGT = TicketCache.getGrantingTicket(String.valueOf(oldGTId));
			
			if (null != oldGT) {
				ConcurrentHashMap<String, ServiceTicket> serviceTicketMap = oldGT
						.getServiceTicketMap();

				Collection<ServiceTicket> stes = serviceTicketMap.values();
				ServiceTicket serviceTicket = null;
				for (Iterator<ServiceTicket> iterator = stes.iterator(); iterator
						.hasNext();) {
					serviceTicket = (ServiceTicket) iterator.next();
					System.out.println("user_"+user.getUserId()+"_kick out====="+serviceTicket.getId());
					SSOUtils.noticeClientLogout(serviceTicket);
				}
				TicketCache.removeGrantingTicket(String.valueOf(oldGTId));
			}
		}
	}
	
	
	/**
	 * 单点退出
	 * @param request
	 * @param response
	 * @param chain
	 * @throws IOException
	 * @throws ServletException
	 */
	public void ssoLogout(HttpServletRequest request,HttpServletResponse response, String gtCookie) {
		// 清除cookie值
		removeSSOCookie(request,response, SSO_COOKIE_NAME);

		GrantingTicket gt = TicketCache.getGrantingTicket(gtCookie);
		if (null != gt) {
			ConcurrentHashMap<String, ServiceTicket> serviceTicketMap = gt
					.getServiceTicketMap();

			Collection<ServiceTicket> stes = serviceTicketMap.values();
			ServiceTicket serviceTicket = null;
			//String host = null;
			for (Iterator<ServiceTicket> iterator = stes.iterator(); iterator
					.hasNext();) {
				serviceTicket = (ServiceTicket) iterator.next();
				
				SSOUtils.noticeClientLogout(serviceTicket);
			}
		}
		TicketCache.removeGrantingTicket(gtCookie);
	}
	
	/**
	 * 客户端跳转
	 * @param request
	 * @param response
	 * @param url
	 * @throws IOException
	 */
	public void sendRedirect(HttpServletRequest request,HttpServletResponse response,String url,Map<String, String[]> requestPram) throws IOException
	{
		if(SSOUtils.isBlank(url))
		{
			return;
		}
		
		
		if(!url.startsWith(SSOConstants.HTTP_PRE))
		{
			url = request.getContextPath()+url;
		}
		
		if(null == requestPram)
		{
			response.sendRedirect(url);
			return;
		}else
		{
			RequestParameter param = new RequestParameter();
			param.setAction(url);
			param.setMethod("post");
			
			param.setRequestPram(requestPram);
			
			generateHtmlFormSubmit(param, request, response);
			return;
		}
	}
	
	
	public void ssoError(HttpServletResponse response,String msg) throws IOException
	{
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println(msg);
		out.flush();
		out.close();
	}
	
	/**
	 * 验证项目合法性
	 * @param response
	 * @param projectCode
	 * @return
	 * @throws IOException 
	 */
	public String validateProject(String projectCode) throws IOException
	{
		
		System.out.println("===========验证项目合法性==============");
		if(StringUtils.isBlank(projectCode))
		{
			return "parameter_invalid";
		}
		
		ProjectEntity p = ProjectCache.getByCode(projectCode);
		if(null==p)
		{
			return "project_unregistered";
		}
		
		return null;
	}
	
	
	
	/**
	 * 根据相关参数生成表单提交html代码
	 * @param param
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	public void generateHtmlFormSubmit(RequestParameter param,HttpServletRequest request,HttpServletResponse response) throws IOException
	{
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
		out.println("<HTML>");
		out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
		out.println("  <BODY>");
		out.println("<form action=\""+param.getAction()+"\" method=\""+param.getMethod()+"\">");
		
		Set<String> paramSet = param.getRequestPram().keySet();
		String paramName = null;
		String[] paramValues = null;
		for (Iterator<String> iterator = paramSet.iterator(); iterator.hasNext();) {
			paramName = iterator.next();
			paramValues = param.getRequestPram().get(paramName);
			for(int i=0;i<paramValues.length;i++)
			{
				out.println("  <INPUT TYPE=\"hidden\" NAME=\""+paramName+"\" value=\""+paramValues[i]+"\">");
			}
		}
    	out.println("  </form>");
		out.println("  </BODY>");
		out.println("</HTML>");
		out.println("<script type=\"text/javascript\"> ");
		out.println("window.document.forms[0].submit();");
		out.println("</script>");
		out.flush();
		out.close();
	}
	
	
	/**
	 * 向jsonp客户端发送用户登录信息
	 */
	public void responseJsonp(HttpServletResponse response,String callback,SSOIdentity ssoId) throws IOException
	{
		ObjectMapper mapper = new ObjectMapper();  
		if(null!=ssoId.getUser())
		{
			ssoId.getUser().setPassword(null);
		}
	    String jsonUser = mapper.writeValueAsString(ssoId);  
		
		StringBuilder jsonpCallback = new StringBuilder();
		jsonpCallback.append(callback);
		jsonpCallback.append("('");
		jsonpCallback.append(jsonUser);
		jsonpCallback.append("');");
		
		System.out.println("jsonUser=="+jsonUser);
		response.setCharacterEncoding("utf-8");
		response.getWriter().print(jsonpCallback.toString());
	}
}